package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.mapper.*;
import cn.wolfcode.wolf2w.business.query.StrategyQuery;
import cn.wolfcode.wolf2w.business.service.IStrategyService;
import cn.wolfcode.wolf2w.business.util.DateUtil;
import cn.wolfcode.wolf2w.business.vo.ThemeVo;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.common.core.context.SecurityContextHolder;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.unit.DataUnit;

import java.security.Key;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 * 
 * @author Tianluhuan
 * @date 2025-09-16
 */
@Service
@Transactional
public class
StrategyServiceImpl extends ServiceImpl<StrategyMapper,Strategy> implements IStrategyService {

    @Autowired
    private StrategyRankMapper  strategyRankMapper;

    @Autowired
    private StrategyThemeMapper  strategyThemeMapper;

    @Autowired
    private StrategyCatalogMapper strategyCatalogMapper;

    @Autowired
    private RemoteDestinationService  remoteDestinationService;

    @Autowired
    private StrategyContentMapper  strategyContentMapper;

    @Autowired
    private StrategyConditionMapper strategyConditionMapper;
    @Autowired
    private RedisService redisService;

    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        QueryWrapper<Strategy> queryWrapper = new QueryWrapper<>();
        if (qo.getType() != null) {
            if (qo.getType() == 2 || qo.getType() == 1) {
                queryWrapper.eq("dest_id", qo.getRefid());
            } else if (qo.getType() == 3) {
                queryWrapper.eq("theme_id", qo.getRefid());
            }
        }
        queryWrapper.orderByDesc(qo.getOrderBy());
        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<Strategy> queryviewnnumTop3(Long destId) {
       return  lambdaQuery().eq(Strategy::getDestId, destId)
               .orderByDesc(Strategy::getViewnum)
                .last("limit 3")
                .list();
    }

    @Override
    public void statisRank() {
        List<Strategy> abordList = lambdaQuery().eq(Strategy::getIsabroad, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();
        List<Strategy> chinaList = lambdaQuery().eq(Strategy::getIsabroad, 0)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();
        List<Strategy> hostList =
                lambdaQuery()
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        Date now = new Date();

        addRank(abordList,now,1L);
        addRank(chinaList,now,2L);
        addRank(hostList,now,3L);
    }
    private void addRank(List<Strategy> list,Date now , Long type){
        for (Strategy strategy:list){
            StrategyRank strategyRank = new StrategyRank();
            strategyRank.setDestId(strategy.getDestId());
            strategyRank.setDestName(strategy.getDestName());
            strategyRank.setStrategyId(strategy.getId());
            strategyRank.setStrategyTitle(strategy.getTitle());
            strategyRank.setType(type);
            strategyRank.setStatisTime(now);
            strategyRank.setStatisnum(strategy.getViewnum());
            strategyRankMapper.insert(strategyRank);
        }
    }


    //主题推荐
    @Override
    public List<ThemeVo> queryTheme() {
        QueryWrapper<Strategy> wrapper = new QueryWrapper<>();
        wrapper.groupBy("theme_name");
        wrapper.select("theme_name, GROUP_CONCAT(DISTINCT dest_id) ids, GROUP_CONCAT(DISTINCT dest_name) names");
        List<Map<String, Object>> list = baseMapper.selectMaps(wrapper);
        List<ThemeVo> themeVoList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            String themeName = (String) map.get("theme_name");
            String ids = map.get("ids").toString();
            String names = (String) map.get("names");
            String[] idAll = ids.split(",");
            String[] nameAll = names.split(",");
            List<Destination> dests = new ArrayList<>();
            for (int i=0; i<idAll.length;i++) {
                Long id = Long.valueOf(idAll[i]);
                String name = nameAll[i];
                Destination dest = new Destination();
                dest.setId(id);
                dest.setName(name);
                dests.add(dest);
            }
            ThemeVo vo = new ThemeVo(themeName,dests);
            themeVoList.add(vo);
        }
        return themeVoList;
    }

    //攻略管理添加
    @Override
    public void insert(Strategy strategy) {
        StrategyTheme theme = strategyThemeMapper.selectById(strategy.getThemeId());
        strategy.setThemeName(theme.getName());
        StrategyCatalog catalog = strategyCatalogMapper.selectById(strategy.getCatalogId());
        strategy.setCatalogName(catalog.getName());
        strategy.setDestId(catalog.getDestId());
        strategy.setDestName(catalog.getDestName());
        strategy.setCreateTime(new Date());
        strategy.setViewnum(0L);
        strategy.setReplynum(0L);
        strategy.setFavornum(0L);
        strategy.setSharenum(0L);
        strategy.setThumbsupnum(0L);
        Boolean b = remoteDestinationService.isbroad(strategy.getDestId(), SecurityConstants.INNER).getData();
        strategy.setIsabroad(b?1L:0L);
        baseMapper.insert(strategy);
        strategy.getContent().setId(strategy.getId());

        strategyContentMapper.insert(strategy.getContent());
    }

    //全部旅游攻略导航查询
    @Override
    public void statisCondition() {
        /**
         * //type=1 查国外
         *         SELECT dest_id refid, dest_name name, COUNT(1) count
         *         from ta_strategy
         *         WHERE isabroad = 1
         *         GROUP BY dest_id, dest_name
         *         ORDER BY count desc
         */
        QueryWrapper<Strategy> wrapper = new QueryWrapper<>();
        wrapper.eq("isabroad", 1);
        wrapper.groupBy("dest_name","dest_id");
        wrapper.select("dest_id refid, dest_name name, COUNT(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> abroadList = baseMapper.selectMaps(wrapper);

        /**
         * #type=2 查国内
         * SELECT dest_id refid, dest_name name, COUNT(1) count
         * from ta_strategy
         * WHERE isabroad = 0
         * GROUP BY dest_id, dest_name
         * ORDER BY count desc
         */
        wrapper.clear();
        wrapper.eq("isabroad", 0);
        wrapper.groupBy("dest_name","dest_id");
        wrapper.select("dest_id refid, dest_name name, COUNT(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> chinaList = baseMapper.selectMaps(wrapper);

        /**
         * #type=3 查主题
         * SELECT theme_id refid, theme_name name, count(1) count
         * from ta_strategy
         * GROUP BY theme_id, theme_name
         * order by count desc
         */
        wrapper.clear();
        wrapper.groupBy("dest_name","dest_id");
        wrapper.select("dest_id refid, dest_name name, COUNT(1) count");
        wrapper.orderByDesc("count");
        List<Map<String, Object>> themeList = baseMapper.selectMaps(wrapper);

        Date date = new Date();

        addCondition(abroadList,date,1L);
        addCondition(chinaList,date,2L);
        addCondition(themeList,date,3L);
    }
    private void addCondition(List<Map<String, Object>> list, Date now , Long type) {
        for (Map<String, Object> map : list) {
            Long refid = Long.valueOf(map.get("refid").toString());
            String name = map.get("name").toString();
            Long count = Long.valueOf(map.get("count").toString());
            StrategyCondition condition = new StrategyCondition();
            condition.setName(name);
            condition.setCount(count);
            condition.setRefid(refid);
            condition.setType(type);
            condition.setStatisTime(now);
            strategyConditionMapper.insert(condition);
        }
    }

    //阅读量++
    @Override
    public Map<String, Object> viewnumIncrease(Long sid) {
        String key = strategyHashInit(sid);
        //阅读量+1
        redisService.incrementCacheMapValue(key,"viewnum",1);
        //重新再查询一遍，避免高并发时发生错误
        Map<String, Object> cacheMap = redisService.getCacheMap(key);
        return cacheMap;
    }

    //评论量
    @Override
    public Map<String, Object> replynumIncrease(Long sid) {
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key,"replynum",1);
        Map<String, Object> cacheMap = redisService.getCacheMap(key);
        return cacheMap;
    }
    private String strategyHashInit(Long sid) {
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if ( ! redisService.hasKey(key)) {
            Strategy strategy = this.getById(sid);
            Map<String,Object> map = new HashMap<>();
            map.put("viewnum",Integer.valueOf(strategy.getViewnum().toString()));
            map.put("replynum",Integer.valueOf(strategy.getReplynum().toString()));
            map.put("sharenum",Integer.valueOf(strategy.getSharenum().toString()));
            map.put("favornum",Integer.valueOf(strategy.getFavornum().toString()));
            map.put("thumbsupnum",Integer.valueOf(strategy.getThumbsupnum().toString()));
            map.put("id",strategy.getId());
            redisService.setCacheMap(key, map);
        }
        return key;
    }

    //收藏++(已收藏：-1 ; 未收擦：+1)
    @Override
    public Map<String, Object> favor(Long sid) {
        //获取当前登录用户
        Long userId = SecurityContextHolder.getUserId();
        //当前用户收藏的key
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(userId.toString());
        //判断redis中是否存在用户收藏的key，不存在时创建,因为HashSet<>里没有数据时，
        // 会自动删除掉所有key，所以要保证里面有数据，存储了一个-1L
        if (!redisService.hasKey(key)) {
            HashSet<Long> sids = new HashSet<>();
            sids.add(-1L);
            redisService.setCacheSet(key,sids);
        }
        boolean b = false;
        String haskey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (redisService.isCacheSetContains(key,sid)){
            //取消收藏
            redisService.incrementCacheMapValue(haskey,"favornum",-1);
            //删除我的收藏里的sid，也就是文档ID
            redisService.deleteCacheSetValue(key,sid);
        }else{
            //添加收藏
            redisService.incrementCacheMapValue(haskey,"favornum",1);
            redisService.addCacheSetValue(key,sid);
            b = true;
        }
        Map<String, Object> cacheMap = redisService.getCacheMap(haskey);
        cacheMap.put("result",b);
        return cacheMap;
    }

    //查询收藏状态
    @Override
    public Boolean isUserFavor(Long uid, Long sid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        if (!redisService.hasKey(key)) {
            HashSet<Long> sids = new HashSet<>();
            sids.add(-1L);
            redisService.setCacheSet(key,sids);
        }
        return redisService.isCacheSetContains(key,sid);
    }

    //redis持久化到mysql
    @Override
    public void strategyStatisHashPersistence() {
        String hashKey = RedisKeys.STRATEGY_STATIS_HASH.join("*");
        Collection<String> keys = redisService.keys(hashKey);
        if (keys != null && keys.size() > 0) {
            for (String key : keys) {
                Map<String, Object> cacheMap = redisService.getCacheMap(key);
                lambdaUpdate().eq(Strategy::getId,cacheMap.get("id"))
                        .set(Strategy::getViewnum,cacheMap.get("viewnum"))
                        .set(Strategy::getSharenum,cacheMap.get("sharenum"))
                        .set(Strategy::getReplynum,cacheMap.get("replynum"))
                        .set(Strategy::getFavornum,cacheMap.get("favornum"))
                        .set(Strategy::getThumbsupnum,cacheMap.get("thumbsupnum"))
                        .update();
            }
        }
    }

    //点赞（一日最多三个赞）
    @Override
    public Map<String, Object> thumbsup(Long sid) {
        //注入uid
        Long uid = SecurityContextHolder.getUserId();
        //拼key
        String key = RedisKeys.USER_STRATEGY_THUMBSUP.join(sid.toString(), uid.toString());

        //计算过期时间
        Date now = new Date();
        Date endDate = DateUtil.getEndDate(now);
        Long seconde = DateUtil.getDateBetween(now, endDate);

        //判断redis中是否有key， 如果没有创建key设置值0
        if( ! redisService.hasKey(key)){
            redisService.setCacheObject(key, 0, seconde, TimeUnit.SECONDS);
        }
        //点赞次数++
        Long ret = redisService.incrementCacheObjectValue(key, 1);

        String hashKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());

        //判断点赞次数，如果大于3，设置result为false
        boolean result = false;
        //如果小于等于3，设置result为true
        if(ret <= 3){
            result = true;
            redisService.incrementCacheMapValue(hashKey, "thumbsupnum", 1);
        }
        //查询统计数字map结构，并将result加入到map中
        Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
        cacheMap.put("result", result);
        //返回map
        return cacheMap;

    }
}
